package com.example.cehua

import android.content.Context
import android.util.AttributeSet
import android.util.Log
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.Scroller
import androidx.viewpager.widget.ViewPager
import java.lang.RuntimeException

/**
 * Imitating SwipeItemLayout Totally
 * 1.侧滑
 * 2.点击关闭侧滑  <->  未侧滑时内容点击生效,否则菜单点击生效
 * 3.
 *
 * 事件总结
 * 1.onInterceptTouchEvent  ACTION_DOWN 一定会执行
 * 2.如果子View 有点击事件(其他事件不清楚),onTouchEvent ACTION_DOWN 不会执行,否则执行
 * 3.onInterceptTouchEvent  ACTION_MOVE 一定会执行,但是拦截后 return true;  就不在执行,交给 onTouchEvent  ACTION_MOVE  执行
 * 4.
 *
 * 事件总结 .II        onInterceptTouchEvent                  onTouchEvent
 * 1.ACTION_DOWN      一定会执行                              如果子View有点击事件(其他事件不清楚)不会执行,否则执行
 *
 * 2.ACTION_MOVE      一定会执行,但是拦截后,就不在执行,        onInterceptTouchEvent拦截后执行
 *                    交给onTouchEvent执行
 *
 * 3.ACTION_UP        子View有事件监听(点击)会执行,否则不执行   与onInterceptTouchEvent相反
 */
class SlideLayout(context: Context, attrs: AttributeSet?) : FrameLayout(context, attrs) {
    private var scroller: Scroller = Scroller(context)

    private var contentWidth = 0
    private var contentHeight = 0
    private var menuWidth = 0


    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        contentWidth = measuredWidth
        contentHeight = measuredHeight

        menuWidth = getChildAt(1).measuredWidth
    }

    override fun measureChild(child: View, parentWidthMeasureSpec: Int, parentHeightMeasureSpec: Int) {
        super.measureChild(child, parentWidthMeasureSpec, parentHeightMeasureSpec)
        val childMeasureSpec =
            ViewGroup.getChildMeasureSpec(parentWidthMeasureSpec, paddingLeft + paddingRight, child.layoutParams.width)
        val childMeasureSpec1 =
            ViewGroup.getChildMeasureSpec(
                parentHeightMeasureSpec, paddingTop + paddingBottom, child.layoutParams.height
            )

        child.measure(childMeasureSpec, childMeasureSpec1)
    }

    override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
        super.onLayout(changed, left, top, right, bottom)
        if (childCount != 2) {
            throw  RuntimeException("SlideLayout 必须有两个子View")
        }
        getChildAt(0).layout(0, 0, right, bottom)
        getChildAt(1).layout(right, 0, right + menuWidth, bottom)
    }

    var downX = 0f
    var downY = 0f
    override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {
        var intercept = false
        when (ev?.action) {
            MotionEvent.ACTION_DOWN -> {
                Log.w("SlideLayout", "--------------------------------------------------")
                Log.w("SlideLayout", "onInterceptTouchEvent    ACTION_DOWN")
                downX = ev.rawX
                downY = ev.rawY
                startX = ev.rawX
                startY = ev.rawY
                closeOtherSlideLayout(this)
            }
            MotionEvent.ACTION_MOVE -> {
                Log.w("SlideLayout", "onInterceptTouchEvent    ACTION_MOVE")
                val endX = ev.rawX
                val endY = ev.rawY
                val dX = downX - endX
                val dY = downY - endY
                if (Math.abs(dX) > Math.abs(dY) && Math.abs(dX) > validDistance) {
                    Log.w("SlideLayout", "onInterceptTouchEvent    ACTION_MOVE  intercept")
                    intercept = true
                }
                validDistance
            }
            MotionEvent.ACTION_UP -> {
                //这个方法后 子View可以响应点击事件
                //跑到这里来,说明  ACTION_MOVE 没有被    子View 和 自己     消费
                val viewX = ev.x
                if (scrollX > 0) {
                    //item 被滑开
                    if (contentWidth - scrollX > viewX) {
                        //点击的是内容部分
                        intercept = true
                        closeMenu()
                    } else {
                        //点击的是菜单部分
                        //如果事件导致  adapter  notifyDataSetChanged(),调用下面的事件才  ->>>>合适<<<<-
                        //否则调用closeMenu()  更合适
                        //如果要确认事件结果,就需要关系到 RecycleView 或 adapter
                        closeMenuS()
//                        closeMenu()
                    }
                } else {
                    //点击的是内容部分
                }
                Log.w("SlideLayout", "onInterceptTouchEvent    ACTION_UP")
            }
        }
        return intercept
    }

    private var startX: Float = 0f
    private var startY: Float = 0f
    private var isSlide = false//是否是滑动事件
    override fun onTouchEvent(event: MotionEvent?): Boolean {
        super.onTouchEvent(event)
        when (event?.action) {
            MotionEvent.ACTION_DOWN -> {
                isSlide = false
                //子View 点击事件 这个方法不会被执行
                Log.w("SlideLayout", "onTouchEvent    ACTION_DOWN")
                touchDown(this)
                startX = event.rawX
                startY = event.rawY
                downX = event.rawX
                downY = event.rawY
            }
            MotionEvent.ACTION_MOVE -> {
                Log.w("SlideLayout", "onTouchEvent    ACTION_MOVE")
                val endX = event.rawX
                val endY = event.rawY

                val distanceX = endX - startX
                var toX = scrollX - distanceX
                if (toX < 0) {
                    toX = 0f
                }
                if (toX > menuWidth) {
                    toX = menuWidth.toFloat()
                }
//                Log.w("SlideLayout", "ACTION_MOVE   toX:$toX")
                scrollTo(toX.toInt(), 0)

                //在X轴和Y轴滑动的距离
                val dX = Math.abs(endX - downX)
                val dY = Math.abs(endY - downY)
                if (dX > dY && dX > 8) {
                    //水平方向滑动
                    //响应侧滑
                    //反拦截-事件给SlideLayout
                    isSlide = true
                    parent.requestDisallowInterceptTouchEvent(true)
                }
                //重置
                startX = endX
                startY = endY
            }
            MotionEvent.ACTION_UP -> {
                Log.w("SlideLayout", "onTouchEvent    ACTION_UP")
                if (scrollX > menuWidth / 2) {
                    if (isSlide) {
                        openMenu()
                    } else {
                        if (event.x < contentWidth - scrollX) {
                            //点击的内容部分执行
                            closeMenu()
                        }
                    }
                } else {
                    closeMenu()
                }
            }
        }
        return true
    }

    private fun openMenu() {
//        scroller.startScroll(scrollX, 0, menuWidth, 0)
        openSlideLayout(this)
        scroller.startScroll(scrollX, scrollY, menuWidth - scrollX, 0 - scrollY, Math.abs(menuWidth - scrollX))
        invalidate()
    }

    /**
     * 直接滑动至初始状态,
     * ->avoiding listView do animation while removing item,you will see the animation be executed on other item
     * ->but,if listView does not remove item,the item would not be recycle,
     * so the function will makes the item show  unreasonable animation(动画别溜,但也解决了,跑到其他 position 去执行动画)
     */
    private fun closeMenuS() {
        scrollTo(0, 0 - scrollY)
    }

    private fun closeMenu() {
        closedSlideLayout()
        scroller.startScroll(scrollX, scrollY, 0 - scrollX, 0 - scrollY, Math.abs(scrollX) * 2)
        invalidate()
    }

    override fun computeScroll() {
        super.computeScroll()
        if (scroller.computeScrollOffset()) {
            //滑动中
            scrollTo(scroller.currX, scroller.currY)
            invalidate()
        }
    }

    companion object {
        private val validDistance = 8
        private var openedSlideLayout: SlideLayout? = null

        fun touchDown(slideLayout: SlideLayout) {
            if (openedSlideLayout != slideLayout) {
                openedSlideLayout?.closeMenu()
            }
        }

        fun closeOtherSlideLayout(slideLayout: SlideLayout) {
            if (openedSlideLayout != null && openedSlideLayout != slideLayout) {
                openedSlideLayout?.closeMenu()
            }
        }

        fun closedSlideLayout() {
            openedSlideLayout = null
        }

        fun openSlideLayout(slideLayout: SlideLayout) {
            openedSlideLayout?.closeMenu()
            openedSlideLayout = slideLayout
        }
    }

    init {
        scroller = Scroller(context)
    }
}